/**
 * 
 */
package org.storagemanagement.services;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.storagemanagement.DAO.ProductExportDao;
import org.storagemanagement.DAO.ProductImportDao;
import org.storagemanagement.DAO.StockDao;
import org.storagemanagement.DAO.StockDaoImpl;
import org.storagemanagement.DO.ProductExportDO;
import org.storagemanagement.DO.ProductImportDO;
import org.storagemanagement.DO.StockDO;
import org.storagemanagement.model.ExportRecordQuery;
import org.storagemanagement.model.ImportRecordQuery;
import org.storagemanagement.model.QuantityWithBatchAndDate;
import org.storagemanagement.model.StockQuery;
import org.storagemanagement.model.StockVO;
import org.storagemanagement.model.StockVOWithBatchList;
import org.storagemanagement.model.StockVOWithExportImportRecord;
import org.storagemanagement.model.StockVOWithImportTime;
import org.storagemanagement.uti.Pair;

/**
 * @author Jason.zhang
 * 
 */
@Service("stockService")
public class StockService {
	@Resource
	private StockDao stockDao;

	@Resource
	private ProductImportDao productImportDao;

	@Resource
	private ProductExportDao productExportDao;
	/**
	 * get stock, each product and batch number to be a line
	 * 
	 */
	public List<StockVO> getStocksByCustomer(String customerId) {
		return getStocks(new StockQuery(customerId));
	}

	/**
	 * get stock, each product and batch number to be a line
	 * 
	 */
	public List<StockVO> getStocks(StockQuery query) {
		List<StockVO> stocks = new ArrayList<StockVO>();
		List<StockDO> stockDOs = stockDao.findStock(query);
		for (StockDO stockDO : stockDOs) {
			StockVO stock = new StockVO();
			stock.setBatchNo(stockDO.getBatchNo());
			stock.setCustomerId(stockDO.getCustomerId());
			stock.setProduct(stockDO.getProduct());
			stock.setQuantity(stockDO.getQuantity());

			stocks.add(stock);
		}
		return stocks;
	}

	/**
	 * 
	 * @return
	 */
	public List<StockVOWithImportTime> getStockWithImportTime(String customerId, String product) {
		List<StockVOWithImportTime> stocks = new ArrayList<StockVOWithImportTime>();
		List<StockDO> stocksDOs = stockDao.findStock(customerId, product);
		for (StockDO stockDO : stocksDOs) {
			StockVOWithImportTime stock = new StockVOWithImportTime();
			stock.setBatchNo(stockDO.getBatchNo());
			stock.setCustomerId(stockDO.getCustomerId());
			stock.setQuantity(stockDO.getQuantity());
			stock.setProduct(stockDO.getProduct());
			stock.setImportTime(stockDO.getGmtModified());
			stocks.add(stock);
		}

		return stocks;
	}

	/**
	 * get stocks, each item with the same product name and customerId will be
	 * shown in the line
	 */
	public List<StockVOWithBatchList> getStocksGroupedByProduct(String customerId) {
		List<StockDO> stockDOs = stockDao.findStock(customerId, "");
		Map<Pair<String, String>, StockVOWithBatchList> stockMap = new HashMap<Pair<String, String>, StockVOWithBatchList>();
		for (StockDO stockDO : stockDOs) {
			Pair<String, String> pair = new Pair<String, String>(stockDO.getCustomerId(), stockDO.getProduct());
			if (stockMap.get(pair) == null) {
				StockVOWithBatchList stockWithBatches = new StockVOWithBatchList();
				stockWithBatches.setCustomerId(stockDO.getCustomerId());
				stockWithBatches.setProduct(stockDO.getProduct());
				stockWithBatches.addStockToList(stockDO);

				stockMap.put(pair, stockWithBatches);
			} else {
				stockMap.get(pair).addStockToList(stockDO);
			}
		}
		return new ArrayList<StockVOWithBatchList>(stockMap.values());
	}

	/**
	 * 
	 * @param stockDO
	 */
	public void addStock(StockDO stockDO) {
		List<StockDO> stocks = stockDao.findStock(new StockQuery(stockDO.getCustomerId(), stockDO.getProduct(), stockDO.getBatchNo()));
		if (CollectionUtils.isEmpty(stocks)) {
			stockDO.setGmtModified(new Date());
			stockDao.save(stockDO);
		}else{
			StockDO stockItem = stocks.get(0);
			stockItem.setQuantity(stockItem.getQuantity() + stockDO.getQuantity());
			stockItem.setGmtModified(new Date());
			stockDao.update(stockItem);
		}
		
	}

	/**
	 * 
	 * @param stockDO
	 */
	public void reduceStock(StockDO stockDO) {
		List<StockDO> stocks = stockDao.findStock(new StockQuery(stockDO.getCustomerId(), stockDO.getProduct(), stockDO.getBatchNo()));
		if (!CollectionUtils.isEmpty(stocks)) {
			StockDO stockItem = stocks.get(0);
			stockItem.setQuantity(stockItem.getQuantity() - stockDO.getQuantity());
			stockItem.setGmtModified(new Date());
			stockDao.update(stockItem);
		}
		
	}
	
	/**
	 * get stock with export import record
	 * 
	 * @return
	 */
	public List<StockVOWithExportImportRecord> getStocksWithExportImportRecord(StockQuery stockQuery) {
		List<StockVOWithExportImportRecord> stockVOWithBatchesList = new ArrayList<StockVOWithExportImportRecord>();
		List<StockDO> stocks = stockDao.findStock(stockQuery);
		for (StockDO stock : stocks) {
			StockVOWithExportImportRecord stockWithBatches = new StockVOWithExportImportRecord();
			stockWithBatches.setCustomerId(stock.getCustomerId());
			stockWithBatches.setProduct(stock.getProduct());

			ImportRecordQuery importQuery = new ImportRecordQuery();
			importQuery.setCustomerId(stock.getCustomerId());
			importQuery.setProduct(stock.getProduct());

			importQuery.setBatchNo(stock.getBatchNo());
			importQuery.setImportDateFrom(stockQuery.getImportDateFrom());
			importQuery.setImportDateTo(stockQuery.getImportDateTo());

			List<ProductImportDO> productAddDOs = productImportDao.find(importQuery);
			List<QuantityWithBatchAndDate> quatitiesWithBatchAndDate = new ArrayList<QuantityWithBatchAndDate>();
			for (ProductImportDO productAddDO : productAddDOs) {
				QuantityWithBatchAndDate detail = new QuantityWithBatchAndDate();
				detail.setBatchNo(productAddDO.getBatchNo());
				detail.setQuantity(productAddDO.getQuantity());
				detail.setImport(true);
				detail.setImportExportDate(productAddDO.getImportTime());

				quatitiesWithBatchAndDate.add(detail);
			}
			
			//=========
			ExportRecordQuery exportQuery = new ExportRecordQuery();
			exportQuery.setCustomerId(stock.getCustomerId());
			exportQuery.setProduct(stock.getProduct());

			exportQuery.setBatchNo(stock.getBatchNo());
			exportQuery.setExportDateFrom(stockQuery.getImportDateFrom());
			exportQuery.setExportDateTo(stockQuery.getImportDateTo());

			List<ProductExportDO> productExportDOs = productExportDao.find(exportQuery);
			for (ProductExportDO productExportDO : productExportDOs) {
				QuantityWithBatchAndDate detail = new QuantityWithBatchAndDate();
				detail.setBatchNo(productExportDO.getBatchNo());
				detail.setQuantity(productExportDO.getQuantity());
				detail.setImport(false);
				detail.setImportExportDate(productExportDO.getExportTime());

				quatitiesWithBatchAndDate.add(detail);
			}
			//=========
			
			stockWithBatches.setQuantityWithRecordList(quatitiesWithBatchAndDate);

			stockVOWithBatchesList.add(stockWithBatches);
		}

		return stockVOWithBatchesList;
	}

	public void updateStock(StockDO stockDO) {
		this.stockDao.update(stockDO);
	}

	public void setStockDao(StockDaoImpl stockDao) {
		this.stockDao = stockDao;
	}

	public void setProductImportDao(ProductImportDao productImportDao) {
		this.productImportDao = productImportDao;
	}

	public void setStockDao(StockDao stockDao) {
		this.stockDao = stockDao;
	}

	public void setProductExportDao(ProductExportDao productExportDao) {
		this.productExportDao = productExportDao;
	}

	
}
